<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>基础：10、组件 自定义事件  自定义货币表单</title>
	<script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script>
	<script src="https://cdn.rawgit.com/chrisvfritz/5f0a639590d6e648933416f90ba7ae4e/raw/98739fb8ac6779cb2da11aaa9ab6032e52f3be00/currency-validator.js"></script>
</head>
<body>
	<div id="app">
	  <currency-input label="Price" v-model="price"></currency-input>
	  <currency-input label="Shipping" v-model="shipping"></currency-input>
	  <currency-input label="Handling" v-model="handling"></currency-input>
	  <currency-input label="Discount" v-model="discount"></currency-input>  
	  <p>Total: ${{ total }}</p>
	</div>

	<script type="text/javascript">
		// 下面对自定义货币表单组件进行解析
		// template: 定义了组件的模板，对input标签可能触发的事件绑定处理函数，有input(输入)、focus(聚焦)、blur(失焦)
		// props: 声明了模板中用到的数据的格式，一个是货币值value，另一个是货币标识说明label
		// mounted: 在子组件完成对父组件的绑定后所处阶段，这里对表单的初始化数据进行了格式化处理
		// methods: 定义了表单各种事件发生了相应的处理函数
		Vue.component('currency-input', {
			template: '\
				<div>\
					<label v-if="label">{{ label }}</label>\
					$\
					<input\
						ref="input"\
						v-bind:value="value"\
						v-on:input="updateValue($event.target.value)"\
						v-on:focus="selectAll"\
						v-on:blur="formatValue"\
					>\
				</div>\
			',
			props: {
				value: {
					type: Number,
					default: 0
				},
				label: {
					type: String,
					default: ''
				}
			},
			// mounted在demo8中有演示，指vue生命周期中完成对实例的el属性绑定到DOM元素后所处的阶段
			mounted: function(){
				this.formatValue()
			},
			methods: {
				// 更新货币金额数值
			    updateValue: function (value) {
			      var result = currencyValidator.parse(value, this.value)
			      if (result.warning) {
			        this.$refs.input.value = result.value
			      }
			      // $emit第一个参数是触发的事件，result.value是传给监听器(这里的监听器就是使用了该组件的vue实例)回调的附加参数
			      this.$emit('input', result.value)    
			    },
			    // 对货币金额数值进行格式化
			    formatValue: function () {
			      this.$refs.input.value = currencyValidator.format(this.value)
			    },
			    selectAll: function (event) {
			      // Workaround for Safari bug
			      // http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome
			      setTimeout(function () {
			      	event.target.select()
			      }, 0)
			    }
			 }			
		})

		// 定义完货币组件后，我们对表单数据进行处理和格式化的操作完全封装在组件定义中
		// 对父组件来说：不需要知道表单数据处理的具体操作，只需要处理完后子组件发出信号并且把数据回调给他即可
		// 对子组件来说：专注于要处理的数据，父组件怎么使用显示他的数据，他不需要关心
		// 这实现了解耦，我们很容易造出我们需要的页面元素轮子，创造自己的输入类型
		new Vue({
			el: '#app',
			data: {
				price: 0,
				shipping: 0,
				handling: 0,
				discount: 0
			},
			computed: {
				total: function(){
					return ((
						this.price * 100 +
						this.shipping * 100 +
						this.handling * 100 -
						this.discount * 100
					) / 100).toFixed(2)
				}
			}
		})
	</script>
</body>
</html>
<!-- 代码均通过测试，有什么纰漏欢迎联系 QQ:1123176978  Wechat:hyhlovehuanong -->